package com.polaris.live.ui.login

import android.content.Intent
import android.os.Bundle
import androidx.annotation.CallSuper
import androidx.annotation.StringRes
import androidx.core.os.bundleOf
import androidx.lifecycle.viewModelScope
import androidx.viewbinding.ViewBinding
import com.blankj.utilcode.util.StringUtils
import com.google.android.gms.auth.api.signin.GoogleSignIn
import com.google.android.gms.auth.api.signin.GoogleSignInAccount
import com.google.android.gms.auth.api.signin.GoogleSignInOptions
import com.google.android.gms.common.api.ApiException
import com.google.android.gms.tasks.Task
import com.google.android.recaptcha.RecaptchaAction
import com.google.firebase.analytics.ktx.analytics
import com.google.firebase.ktx.Firebase
import com.lxj.xpopup.XPopup
import com.lxj.xpopup.core.BasePopupView
import com.polaris.live.R
import com.polaris.live.common.constant.CommonConst
import com.polaris.live.common.mvvm.activity.showLoading
import com.polaris.live.common.mvvm.base2.BaseVbActivity
import com.polaris.live.common.network.parseState
import com.polaris.live.common.network.state.ResultState
import com.polaris.live.common.resp.UserResp
import com.polaris.live.common.util.JsonUtils
import com.polaris.live.common.util.ToastGravity
import com.polaris.live.constant.EventConst
import com.polaris.live.constant.TrackEventConst.EVENT_CLOSE_UC
import com.polaris.live.constant.TrackEventConst.EVENT_CONTINUE_UC
import com.polaris.live.constant.TrackEventConst.EVENT_ITEM_UC
import com.polaris.live.constant.TrackEventConst.LOGIN_ACTIVITY
import com.polaris.live.constant.TrackEventConst.TRACK_DIALOG
import com.polaris.live.dialog.GlobalDialogManager
import com.polaris.live.dialog.PrivacyConfirmDialog
import com.polaris.live.interface_bag.XpopupCallBackImpl
import com.polaris.live.manager.AppConfigManager
import com.polaris.live.manager.GoogleRecaptchaManager
import com.polaris.live.translation.R.string
import com.polaris.live.ui.main.activity.MainActivity
import com.polaris.live.utils.TrackHelper
import com.polaris.live.utils.UserUtils
import com.polaris.live.utils.postEvent
import com.polaris.live.utils.route.RoutePath
import com.polaris.live.utils.route.Router
import com.polaris.live.viewmodel.login.LoginViewModel
import kotlinx.coroutines.launch

/**
 * BaseGoogleLoginActivity
 *
 * @author Created by lucas on 2023/11/22 11:42
 */
abstract class BaseGoogleLoginActivity<VM : LoginViewModel, VB : ViewBinding> :
    BaseVbActivity<VM, VB>() {

    @CallSuper
    override fun initView(savedInstanceState: Bundle?) {
        googleObserver()
    }

    private fun googleObserver() {
        mViewModel.gotoLoginLiveData.observe(this) {
            when (it) {
                LoginViewModel.GOTO_PHONE -> {
                    Router.instance.setPath(RoutePath.PHONE_NUMBER_ACTIVITY).navigation(this)
                }

                LoginViewModel.GOTO_GOOGLE -> {
                    showLoading(string.google_logining, cancelable = true)

                    launchGoogle()
                }


                LoginViewModel.GOTO_GMAIL -> {
                    Router.instance.setPath(RoutePath.GMAIL_ACTIVITY).navigation(this)
                }

                LoginViewModel.GOTO_DEVICE -> {
                    showLoading(string.device_logining)

                    lunchQuickStart()
                }
            }
        }
        mViewModel.googleLoginLiveData.observe(this) { resultState ->
            invokeLoginSuccess(LoginViewModel.GOTO_GOOGLE, resultState)
        }
        mViewModel.deviceLoginLiveData.observe(this) { resultState ->
            invokeLoginSuccess(LoginViewModel.GOTO_DEVICE, resultState)
        }
    }

    private fun invokeLoginSuccess(type: Int, resultState: ResultState<UserResp>) {
        dismissLoading()
        parseState(resultState, {
            if (it.registered == true) {
                when (type) {
                    LoginViewModel.GOTO_GOOGLE -> {
                        Firebase.analytics.postEvent(
                            EventConst.SUCCESS_REGISTER,
                            bundleOf("type" to "google")
                        )
                    }

                    LoginViewModel.GOTO_DEVICE -> {
                        Firebase.analytics.postEvent(
                            EventConst.SUCCESS_REGISTER,
                            bundleOf("type" to "device")
                        )
                    }
                }
            }

            UserUtils.loginSuccess(it)
            startActivity(Intent(this, MainActivity::class.java))
            finish()
        }, {
            if (it.errCode == CommonConst.ErrorCode.SEAL_ACCOUNT || it.errCode == CommonConst.ErrorCode.SEAL_ACCOUNT_LOGIN || it.errCode == CommonConst.ErrorCode.SEAL_ACCOUNT_STOP) {
                GlobalDialogManager.showSealAccountDialog(this, JsonUtils.toJson(it.ext))
            } else {
                ToastGravity.showGravity(it.errorMsg)
            }
        })
    }

    protected fun launchGoogle() {
        val googleSignInOptions = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
            .requestId()
            .requestIdToken(getString(R.string.server_client_id))
            .requestEmail()
            .requestProfile()
            .build()

        val googleSignInClient = GoogleSignIn.getClient(this, googleSignInOptions)

        //先将之前登陆的账号下线处理
        googleSignInClient.signOut()

        startActivityForResult(googleSignInClient.signInIntent, SIGN_IN_GOOGLE)
    }

    /**
     * 处理Google登录的结果
     */
    private fun handleSignInResult(task: Task<GoogleSignInAccount>) {
        try {
            //不管什么方式失败也要关闭loading弹窗
            dismissLoading()
            val account = task.getResult(ApiException::class.java)
            if (account == null) {
                googleFailure(string.google_login_failure)
                return
            }

            val id = account.id
            val idToken = account.idToken
            if (id == null || idToken == null) {
                googleFailure(string.google_login_failure)
                return
            }

            googleLoginSuccess(id.toString(), idToken)
        } catch (e: ApiException) {
            e.printStackTrace()

            if (!e.status.isCanceled && e.statusCode != 12501) {
                googleFailure(e.message, e)
            } else {
                dismissLoading()
            }
        }
    }

    private fun googleFailure(@StringRes resId: Int, t: ApiException? = null) {
        googleFailure(StringUtils.getString(resId), t)
    }

    private fun googleFailure(message: String?, t: ApiException? = null) {
        Firebase.analytics.postEvent(
            EventConst.GOOGLE_LOGIN_FAILURE,
            bundleOf(
                "error" to message,
                "status" to t?.statusCode
            )
        )

        ToastGravity.showGravity(message ?: StringUtils.getString(string.google_login_failure))
        dismissLoading()
    }

    protected open fun googleLoginSuccess(id: String, token: String) {
        mViewModel.googleLogin(id, token)
    }

    private fun lunchQuickStart() {
        mViewModel.deviceLogin()
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)

        if (requestCode == SIGN_IN_GOOGLE) {
            val task = GoogleSignIn.getSignedInAccountFromIntent(data)
            handleSignInResult(task)
        }
    }

    /**
     * google登录
     */
    fun gotoGoogleLogin() {
        mViewModel.gotoLogin(LoginViewModel.GOTO_GOOGLE)
    }

    /**
     * google登录并且验证是否同意协议
     */
    fun gotoGoogleLoginAndCheck(isCheck: Boolean, onSelectedCheck: () -> Unit) {
        gotoLoginAndCheck(LoginViewModel.GOTO_GOOGLE, isCheck, onSelectedCheck)
    }

    /**
     * facebook登录并且验证是否同意协议
     */
    private fun gotoLoginAndCheck(
        type: Int,
        isCheck: Boolean,
        onSelectedCheck: () -> Unit,
    ) {
        if (!isCheck) {
            XPopup.Builder(this)
                .isDestroyOnDismiss(true)
                .setPopupCallback(object : XpopupCallBackImpl {
                    override fun onShow(popupView: BasePopupView) {
                        super.onShow(popupView)
                        TrackHelper.postTrack(
                            LOGIN_ACTIVITY,
                            EVENT_ITEM_UC,
                            TRACK_DIALOG,
                            TrackHelper.loginForMap(),
                        )
                    }
                })
                .asCustom(
                    PrivacyConfirmDialog(
                        this,
                        callBack = {
                            onSelectedCheck()
                            if (it) {
                                TrackHelper.postTrack(
                                    LOGIN_ACTIVITY,
                                    EVENT_CONTINUE_UC,
                                    params = TrackHelper.loginForMap()
                                )
                                mViewModel.gotoLogin(type)
                            } else {
                                TrackHelper.postTrack(
                                    LOGIN_ACTIVITY,
                                    EVENT_CLOSE_UC,
                                    params = TrackHelper.loginForMap()
                                )
                            }
                        })
                )
                .show()
        } else {
            mViewModel.gotoLogin(type)
        }
    }

    /**
     * google人机验证
     */
    fun verifyGoogle(
        onFailureListener: ((Throwable) -> Unit)? = null,
        onSuccessListener: (String?) -> Unit,
    ) {
        if (AppConfigManager.getConfig(CommonConst.Configs.smsVerifySwitch) == "false") {
            onSuccessListener(null)
            return
        }
        val recaptchaClient = GoogleRecaptchaManager.recaptchaClient
        if (recaptchaClient == null) {
            handleError(IllegalStateException("google init failure"), onFailureListener)
            return
        }

        mViewModel.viewModelScope.launch {
            recaptchaClient.execute(RecaptchaAction.LOGIN, 15 * 1000)
                .onSuccess {
                    onSuccessListener(it)
                }
                .onFailure {
                    handleError(it, onFailureListener)
                }
        }
    }

    private fun handleError(e: Throwable, onFailureListener: ((Throwable) -> Unit)?) {
        Firebase.analytics.postEvent(
            EventConst.GOOGLE_VERIFY_FAILURE,
            bundleOf(
                "error" to e.stackTraceToString()
            )
        )

        if (onFailureListener == null) {
            if (e is ApiException) {
                ToastGravity.showGravity(e.message)
            } else {
                ToastGravity.showGravity(string.google_verify_failure)
            }
        } else {
            onFailureListener(e)
        }

        e.printStackTrace()
    }

    companion object {

        const val SIGN_IN_GOOGLE = 10000
    }
}